package m.common.action;

import m.appserver.AuthInfoUtil;
import m.system.cache.CacheUtil;
import m.system.db.TransactionManager;
import m.system.exception.MException;
import m.system.util.JSONMessage;
import m.system.util.NumberUtil;
import m.system.util.StringUtil;
import m.system.util.SystemUtil;
import manage.util.DictionaryUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public abstract class ImportExcelAction extends Action {
	private String importParam;
	/** 子类继承
	 * 处理上传文件的数据
	 *  data 数据
	 *  处理成功消息
	 *  Exception 错误信息
	 */
	protected String processImportData(List<String[]> data,String importParam) throws Exception{
		throw new MException(this.getClass(), "未实现导入方法");
	}
	private String doProcessImportData(List<String[]> data,String importParam){
		new Thread(() -> {
			AuthInfoUtil.reset(getRequest());
			try {
				this.startImportProgress();
				this.endImportProgress(processImportData(data,importParam));
			} catch (Exception e) {
				this.errorImportProgress(e.getMessage());
				SystemUtil.println(e.getMessage());

			} finally {
				AuthInfoUtil.clear();
				TransactionManager.closeConnection();
			}
		}).start();
		return "已启动导入";
	}

	/** 子类继承
	 * 上传页面打开时获取设置信息
	 * {
	 * 	importParam, //可修改打开页面时的importParam
	 * 	tempPath,	//模板路径 站点根目录开始
	 * 	tempName,	//模板文件名
	 * 	tempType,	//模板类型 默认download下载 page站内打开 open新页面打开
	 * 	title,	//导入页面标题
	 * 	subTitle,	//导入页面子标题
	 * 	alertMessage,	//提示消息
	 * 	canStop,	//是否可中止  processImportData中需要调用isStopImport判断是否中止
	 * 	autoSubmit	//自动提交 默认false,processImportData中需要加事务，发现错误回滚全部，true则实时操作数据库
	 * }
	 */
	protected JSONMessage processImportSetting(String importParam){
		return new JSONMessage();
	}

	/** 导入页面调用
	 * 获取导入页面配置
	 */
	public JSONMessage getImportExcelSetting(){
		return processImportSetting(importParam);
	}

	/** processImportData 导入方法内调用，可在页面显示进度
	 * 设置导入的总数量
	 */
	protected void setImportCountNum(int countNum){
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_count"),countNum,43200);
	}
	/** processImportData 导入方法内调用，可在页面显示进度
	 * 设置导入的当前数
	 */
	protected void setImportCurrentNum(int currentNum){
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_num"),currentNum,43200);
	}
	/** processImportData 导入方法内调用，可在页面显示进度
	 * 设置导入的当前标题
	 */
	protected void setImportCurrentTitle(String currentTitle){
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_title"),currentTitle,43200);
	}
	/** processImportData 导入方法内调用，可在页面显示进度
	 * 设置导入时展示的消息
	 */
	protected void setImportMessage(String message){
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_message"),message,43200);
	}
	/** processImportData 导入方法内调用
	 * 用于判断用户是否中止
	 */
	protected boolean isStopImport(){
		Object b=CacheUtil.getLocal(AuthInfoUtil.getSession("_import_stop"));
		if(null!=b){
			return (boolean) b;
		}
		return false;
	}
	/** 导入页面调用
	 * 获取导入进度
	 */
	public JSONMessage getImportProgress(){
		return new JSONMessage()
			.push("import", CacheUtil.getLocal(AuthInfoUtil.getSession("_import_status")))//Y正在导入,N导入失败 空，当前没有任务
			.push("message", CacheUtil.getLocal(AuthInfoUtil.getSession("_import_message")))//失败原因
			.push("title", CacheUtil.getLocal(AuthInfoUtil.getSession("_import_title")))//当前导入标题
			.push("start", CacheUtil.getLocal(AuthInfoUtil.getSession("_import_start")))//导入开始时间
			.push("count", CacheUtil.getLocal(AuthInfoUtil.getSession("_import_count")))//导入总记录数
			.push("current", CacheUtil.getLocal(AuthInfoUtil.getSession("_import_num")));//当前正在导入数
	}

	/** 导入页面调用
	 * 清除导入状态
	 */
	public JSONMessage clearImportProgress(){
		CacheUtil.clear(AuthInfoUtil.getSession("_import_status"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_message"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_title"));
		return new JSONMessage();
	}
	/** 导入页面调用
	 * 停止导入
	 */
	public JSONMessage stopImportProgress(){
		Object status=CacheUtil.getLocal(AuthInfoUtil.getSession("_import_status"));
		if(null!=status&&"Y".equals(status.toString())) {
			CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_stop"), true, 43200);
		}
		return new JSONMessage();
	}
	private void startImportProgress(){
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_status"),"Y",43200);
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_start"),m.system.util.DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),43200);
	}
	private void endImportProgress(String message){
		CacheUtil.clear(AuthInfoUtil.getSession("_import_status"));
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_message"),message,43200);
		CacheUtil.clear(AuthInfoUtil.getSession("_import_start"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_count"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_num"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_stop"));
	}
	private void errorImportProgress(String message){
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_status"),"N",43200);
		CacheUtil.pushLocal(AuthInfoUtil.getSession("_import_message"),message,43200);
		CacheUtil.clear(AuthInfoUtil.getSession("_import_start"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_count"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_num"));
		CacheUtil.clear(AuthInfoUtil.getSession("_import_stop"));
	}
	/** 导入页面调用
	 * action 导入方法
	 */
	public JSONMessage importExcel(){
		JSONMessage message=new JSONMessage();
		Workbook work=null;
		FileInputStream is=null;
		try {
			if("Y".equals(CacheUtil.getLocal(AuthInfoUtil.getSession("_import_status")))){
				throw new MException(this.getClass(),"当前浏览器正在导入，请勿重复导入或者同时导入。");
			}
			List<String[]> list= new ArrayList<>();
			Map<String,File> fileMap=getFileMap();
			if(fileMap.isEmpty()) throw new MException(this.getClass(),"没有接收到Excel文件");
			for(String key : fileMap.keySet()){
				File file=fileMap.get(key);
				is=new FileInputStream(file);
				if (file.getName().endsWith(".xls")) {
					work = new HSSFWorkbook(is);
				} else if (file.getName().endsWith(".xlsx")) {
					work = new XSSFWorkbook(is);
				} else {
					throw new Exception("请选择xls或者xlsx文件");
				}
				Sheet sheet = work.getSheetAt(0);
				for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
					Row row=sheet.getRow(i);
					int cells=row.getLastCellNum();
					if(cells<0) continue;
					String[] strs=new String[cells];
					for (int j = 0; j < cells; j++) {
						Cell cell = row.getCell(j);
						strs[j]=getCellValue(cell);
					}
					list.add(strs);
				}
			}
			if(list.isEmpty()) throw new Exception("Excel文件中没有数据!");
			message.push("msg", doProcessImportData(list,importParam));
			message.push("code",0);
		} catch (Exception e) {
			e.printStackTrace();
			message.push("msg", e.getMessage());
			message.push("code",1);
		}finally{
			try {
				if(null!=work) work.close();
			} catch (IOException ignored) {}
			try {
				if(null!=is) is.close();
			} catch (IOException ignored) {}
		}
		//SystemUtil.println(message.toJSONString());
		return message;
	}

	private static String getCellValue(Cell cell) {
		if(null==cell) return null;
		CellType cellType = cell.getCellType();
		String cellValue = null;
		if (cellType == CellType._NONE) {
		} else if (cellType == CellType.NUMERIC) {
			// 数值型
			if (DateUtil.isCellDateFormatted(cell)) {
				// 日期类型
				Date d = cell.getDateCellValue();
				cellValue = m.system.util.DateUtil.format(d,"yyyy-MM-dd HH:mm:ss");
			} else {
				cellValue = NumberUtil.format(cell.getNumericCellValue(), "0.#######");
			}
		} else if (cellType == CellType.STRING) {
			// 字符串型
			cellValue = cell.getStringCellValue();
		} else if (cellType == CellType.FORMULA) {
			// 公式型
			try {
				cellValue = cell.getStringCellValue();
			} catch (IllegalStateException e) {
				cellValue = NumberUtil.format(cell.getNumericCellValue(), "0.#######");
			}
		} else if (cellType == CellType.BLANK) {
			// 空值
		} else if (cellType == CellType.BOOLEAN) {
			// 布尔型
			cellValue = String.valueOf(cell.getBooleanCellValue());
		} else if (cellType == CellType.ERROR) {
			// 错误
			cellValue = String.valueOf(cell.getErrorCellValue());
		}
		return null!=cellValue?cellValue.trim():null;
	}

	/**
	 * 转换行数组长度
	 */
	protected String[] parseRowData(String[] row,int length){
		String[] data=new String[length];
		System.arraycopy(row, 0, data, 0, Math.min(row.length, length));
		return data;
	}
	/**
	 * 转换double类型
	 */
	protected Double parseDouble(String str,int row,String name,StringBuffer errorMessage) {
		if(StringUtil.isSpace(str)){
			return null;
		}
		try{
			return Double.parseDouble(str);
		}catch(NumberFormatException e){
			errorMessage.append("\r\n第").append(row).append("行").append(name).append("数字格式化出错！错误值：").append(str);
		}
		return null;
	}
	/**
	 * 转换double类型 不为空
	 */
	protected Double parseDoubleNotNull(String str,int row,String name,StringBuffer errorMessage){
		Double d=parseDouble(str,row,name,errorMessage);
		if(null==d){
			errorMessage.append("\r\n第").append(row).append("行").append(name).append("不能为空！");
		}
		return d;
	}
	/**
	 * 转换Integer类型
	 */
	protected Integer parseInteger(String str,int row,String name,StringBuffer errorMessage) {
		if(StringUtil.isSpace(str)){
			return null;
		}
		try{
			return Integer.parseInt(str);
		}catch(NumberFormatException e){
			errorMessage.append("\r\n第").append(row).append("行").append(name).append("整型格式化出错！错误值：").append(str);
		}
		return null;
	}
	/**
	 * 转换Integer类型 不为空
	 */
	protected Integer parseIntegerNotNull(String str,int row,String name,StringBuffer errorMessage){
		Integer d=parseInteger(str,row,name,errorMessage);
		if(null==d){
			errorMessage.append("\r\n第").append(row).append("行").append(name).append("不能为空！");
		}
		return d;
	}
	/**
	 * 转换Date类型
	 */
	protected Date parseDate(String str,int row,String name,StringBuffer errorMessage) {
		if(StringUtil.isSpace(str)){
			return null;
		}
		try{
			return m.system.util.DateUtil.format(str, "yyyy-MM-dd HH:mm:ss".substring(0,str.length()));
		}catch(NumberFormatException e){
			errorMessage.append("\r\n第").append(row).append("行").append(name).append("日期时间格式化出错！错误值：").append(str);
		}
		return null;
	}
	/**
	 * 转换Date类型 不为空
	 */
	protected Date parseDateNotNull(String str,int row,String name,StringBuffer errorMessage){
		Date d=parseDate(str,row,name,errorMessage);
		if(null==d){
			errorMessage.append("\r\n第").append(row).append("行").append(name).append("不能为空！");
		}
		return d;
	}
	/**
	 * 获取字典真实值 如果str是真实值,直接返回
	 */
	protected String parseDictValue(String str,String dictType,int row,String name,StringBuffer error){
		if(StringUtil.isSpace(str)){
			return null;
		}
		String t=DictionaryUtil.getName(dictType,str);//假设str是真实值 然会的t(显示值)不等于str，就说明找到了，str就是真实值
		if(!StringUtil.noSpace(t).equals(str)) return str;//取到显示值和str不等，则返回str
		String value= DictionaryUtil.getValue(dictType,str);
		if(null==value){
			error.append("\r\n第").append(row).append("行").append(name).append("值错误！错误值：").append(str);
		}
		return value;
	}
	/**
	 * 获取字典真实值 不为空
	 */
	protected String parseDictValueNotNull(String str,String dictType,int row,String name,StringBuffer error){
		String d=parseDictValue(str,dictType,row,name,error);
		if(null==d){
			error.append("\r\n第").append(row).append("行").append(name).append("不能为空！");
		}
		return d;
	}

	/**
	 * 转换字符串，空字符串转换成null
	 */
	protected String parseString(String str){
		if(StringUtil.isSpace(str)){
			return null;
		}
		return str;
	}

	public String getImportParam() {
		return importParam;
	}

	public void setImportParam(String importParam) {
		this.importParam = importParam;
	}
}
